//common functions used in Bristleback




//create new application (as global object, add all functions to this object
var Bristle = Bristle || {};


Bristle.BaseConnector = function() {
  this.name = "base connector";
};

Bristle.BaseConnector.prototype = new jws.jWebSocketJSONClient();


//container for named actions
Bristle.actionNames = {
  LOG_IN_ACTION_NAME : "LOG_IN_ACTION_NAME",
  LOG_OFF_ACTION_NAME : "LOG_OFF_ACTION_NAME"
};

Bristle.EXCEPTION_TYPE = '_B_EX_T';
Bristle.EXCEPTION_VALUE = '_B_EX_V';

WEB_SOCKET_SWF_LOCATION = "js/flash-bridge/WebSocketMain.swf";   // required by jwebsocket.js

function createCallback(onSuccessFunction, onFailureFunction) {
  return {
    onSuccess: onSuccessFunction,
    onFailure: onFailureFunction
  };
}

function createDefaultFailureCallback() {
  return function(exception) {
    alert("Exception with name: " + exception.getExceptionType());
  }
}

Bristle.addCallback = function(callback) {
  var callbackObject;
  if (callback) {
    if (callback instanceof Function) {
      var onFailureFunction = createDefaultFailureCallback();
      callbackObject = createCallback(callback, onFailureFunction);
    } else if (callback instanceof Object) {
      if (!callback.onSuccess) {
        throw new Error("Callback object must contain onSuccess(response) method.");
      }
      callbackObject = callback;
      if (!callback.onFailure) {
        callback.onFailure = createDefaultFailureCallback();
      }
    }
    return callbackObject;
  }
};

Bristle.parseJSON = function(json) {
  return jQuery.parseJSON(json);
};


Bristle.deepCopy = function(p, c) {
  var c = c || {};
  for (var i in p) {
    if (typeof p[i] === 'object') {
      c[i] = (p[i].constructor === Array) ? [] : {};
      Bristle.deepCopy(p[i], c[i]);
    } else {
      if (typeof p[i] !== 'function') {
        c[i] = p[i];
      }
    }
  }
  return c;
};

Bristle.objectToString = function(obj) {
  var objectAsString = "";
  var innerObject = "";
  var startMark = "{";
  var endMark = "}";
  for (var field in obj) {
    if (typeof obj[field] === 'object') {
      if (obj[field] instanceof Array) {
        startMark = "[";
        endMark = "]";
      }
      innerObject = Bristle.objectToString(obj[field]);
      if (innerObject != "") {
        objectAsString += field + " " + startMark + "\n";
        objectAsString += innerObject;
        objectAsString += endMark + "\n";
      }
    } else {
      if (!(obj[field] instanceof Function)) {
        objectAsString += field + ": " + obj[field] + "\n";
      }
    }
  }
  return objectAsString;
};

Bristle.formToObject = function(formId) {

  function getPathObject(parent, fieldName, isLastElement, formElement) {
    var value = getValue(formElement, {}, isLastElement);
    return getPathElement(parent, fieldName, isLastElement, value);
  }

  function getPathArray(parent, fieldName, isLastElement, formElement) {
    var value = getValue(formElement, [], isLastElement);
    return getPathElement(parent, fieldName, isLastElement, value);
  }

  function getValue(formElement, defaultValue, isLastElement) {
    if (isLastElement) {
      return formElement.value;
    } else {
      return defaultValue;
    }
  }

  function getPathElement(parent, fieldName, isLastElement, element) {
    if (isLastElement) {
      setValue(parent, fieldName, element);
      return parent[fieldName];
    } else {
      return getNestedField(parent, fieldName, element);
    }
  }

  function getNestedField(parent, fieldName, element) {
    if (parent[fieldName] === undefined) {
      parent[fieldName] = element;
    }
    return parent[fieldName];
  }

  function setValue(parent, fieldName, element) {
    if (parent[fieldName] === undefined) {
      parent[fieldName] = element;
    } else if (parent[fieldName] instanceof Array) {
      parent[fieldName].push(element);
    } else {
      parent[fieldName] = [parent[fieldName]];
      parent[fieldName].push(element);
    }

    return parent[fieldName];
  }

  function processArray(pathElementName, propertyPathObject, formElement, isLastElement) {
    var prefix = pathElementName.substring(0, pathElementName.indexOf('['));
    var indexSuffix = pathElementName.substring(pathElementName.indexOf('[') + 1, pathElementName.indexOf(']'));
    propertyPathObject = getPathArray(propertyPathObject, prefix, false, formElement);
    propertyPathObject = getPathObject(propertyPathObject, indexSuffix, isLastElement, formElement);
    return propertyPathObject;
  }

  function processMap(pathElementName, propertyPathObject, formElement, isLastElement) {
    var prefix = pathElementName.substring(0, pathElementName.indexOf('['));
    var indexSuffix = pathElementName.substring(pathElementName.indexOf('[') + 1, pathElementName.indexOf(']'));
    propertyPathObject = getPathObject(propertyPathObject, prefix, false, formElement);
    propertyPathObject = getPathObject(propertyPathObject, indexSuffix, isLastElement, formElement);
    return propertyPathObject;
  }

  var simpleFieldPattern = /^[\-_0-9a-z]+$/i;
  var mapPattern = /^[\-_0-9a-z]+\[[0-9a-z]+\]$/i;
  var arrayPattern = /^[\-_0-9a-z]+\[[0-9]+\]$/i;
  var array = $(formId).serializeArray();

  var result = {};

  for (var index in array) {
    var formElement = array[index];
    var propertyPath = formElement.name.split('.');
    var propertyPathObject = result;
    for (var pathIndex = 0; pathIndex < propertyPath.length; pathIndex++) {
      var isLastElement = pathIndex == propertyPath.length - 1;
      var pathElementName = propertyPath[pathIndex];
      if (simpleFieldPattern.test(pathElementName)) {
        propertyPathObject = getPathObject(propertyPathObject, pathElementName, isLastElement, formElement)
      } else if (arrayPattern.test(pathElementName)) {
        propertyPathObject = processArray(pathElementName, propertyPathObject, formElement, isLastElement);
      } else if (mapPattern.test(pathElementName)) {
        propertyPathObject = processMap(pathElementName, propertyPathObject, formElement, isLastElement);
      }
    }
  }

  return result;
};

Bristle.log = function(msg) {
  if (jws.BristlePlugIn.developmentConsole) {
    var console = $("#bristleConsole");
    if (console == undefined) {
      return;
    }
    console.append(msg);
    console.attr("scrollTop", console.attr("scrollHeight"));
  }
};

Bristle.appendConsole = function() {
  $('body').append("<div id='bristleConsole' style='font-size: 10pt; position: absolute; bottom: 0; left: 0; width:98%; height: 100px; border: solid 1px #dcdcdc; overflow-y: scroll; padding: 2px;'>Bristleback console v0.1<br></div>");
};

var EventNotHandledError = function(typeError) {
  this.error = typeError;
  this.toString = function() {
    var eventName = this.error.toString().match(/'.*'/);
    return "EventNotHandledError\nEvent not handled by framework!\nEvent name: " + eventName;
  }

};

/**
 * Function used to prevent cross site scripting.
 * You should used it on every message from server that you want to insert into DOM.
 * @param text to escape characters
 */
Bristle.escapeHTML = function(txt) {
  var div = document.createElement('div');
  var text = document.createTextNode(txt);
  div.appendChild(text);
  return div.innerHTML;
}
